#include "stdafx.h"
#include <assert.h>
#include <xwt/xwt_view.h>

xwt::View::View () {	
	m_opacity = 1.0f;
	m_cached_gc = NULL;
	m_isDoubleBuffered = false;
}

xwt::View::~View () {
}

bool xwt::View::Create (int x, int y, int cx, int cy) {
	if ( Window::Create (0, 0, 1, 1, NULL) ) {
	#ifdef WIN32
		// set style bits for a view
		LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
		
		style&= ~WS_CAPTION; // remove title bar

		style&= ~WS_VISIBLE; // set auto visible FALSE		

		::SetWindowLong ( m_hWnd, GWL_STYLE, style );

		// resize the view
		MoveWindow (GetHandle(), x, y, cx, cy, FALSE);				
	#endif

		return true;
	}

	return false;
}

void xwt::View::AddSubView (View *pSubView) {
	XWT_ASSERT (pSubView && pSubView->IsValid());

#ifdef WIN32
	LONG style = ::GetWindowLong (pSubView->GetHandle(), GWL_STYLE);
	style|= WS_VISIBLE; // set auto visible
	::SetWindowLong ( pSubView->GetHandle(), GWL_STYLE, style );
#endif

	m_subViews.push_back (pSubView);
	AddChild ( pSubView );
}

void xwt::View::RemoveSubView (View *pSubView) {
	// remove from sub view list 
	m_subViews.remove (pSubView);

#ifdef WIN32
	// from from view hierarchy
	::SetParent (pSubView->GetHandle(), NULL);

	// remove WS_CHILD style from the the view
	LONG style = ::GetWindowLong (pSubView->GetHandle(), GWL_STYLE);
	style&= ~WS_CHILD;
	::SetWindowLong ( pSubView->GetHandle(), GWL_STYLE, style );
#endif
}

void xwt::View::RemoveAllSubViews () {
	list<View *>::iterator it;
	
	for (it = m_subViews.begin(); it != m_subViews.end(); it++) {
		View *pSubView = *it;

		// remove from sub view list 
		m_subViews.remove (pSubView);

		// from from view hierarchy
	#ifdef WIN32
		::SetParent (pSubView->GetHandle(), NULL);
		
		// remove WS_CHILD style from the the view
		LONG style = ::GetWindowLong (pSubView->GetHandle(), GWL_STYLE);
		style&= ~WS_CHILD;
		::SetWindowLong ( pSubView->GetHandle(), GWL_STYLE, style );
	#endif
	}

	m_subViews.clear ();
}

void xwt::View::CenterView (Window *pParent) {
#ifdef WIN32
	HWND hWndParent = NULL;

	if (pParent) hWndParent = pParent->GetHandle();
	if (!hWndParent) hWndParent = ::GetDesktopWindow ();

	if (hWndParent) {
		RECT rectDlg, rectParent;
		::GetClientRect ( m_hWnd, &rectDlg );

		::GetClientRect ( hWndParent, &rectParent );

		POINT offset = {
			rectParent.left + (rectParent.right - rectParent.left) / 2 - (rectDlg.right - rectDlg.left) / 2,
			rectParent.top + (rectParent.bottom - rectParent.top) / 2 - (rectDlg.bottom - rectDlg.top) / 2
		};

		::MoveWindow (m_hWnd, offset.x, offset.y, rectDlg.right - rectDlg.left,
						rectDlg.bottom - rectDlg.top, 
						IsWindowVisible(m_hWnd) );
	}
#endif
}

void xwt::View::SetDoubleBuffered (bool flag) {
	if (flag == m_isDoubleBuffered)
		return;

	// #TODO: set or disable double buffering
	if (m_isDoubleBuffered) {

	} else {

	}
}

// rendering...

void xwt::View::RefreshView () {
	CalcLayout ();
#ifdef WIN32
	RECT rect;
	::GetClientRect (GetHandle(), &rect );
	::InvalidateRect ( GetHandle (), &rect, TRUE );
#endif
}

void xwt::View::RedrawView () {
#ifdef WIN32
	RECT rect;
	::GetClientRect (GetHandle(), &rect );
	::InvalidateRect ( GetHandle (), &rect, TRUE );
#endif
}

#ifdef WIN32
void xwt::View::GetCreateStyle (DWORD &dwStyle, DWORD &dwExStyle) {
	dwStyle = WS_OVERLAPPED;
	dwExStyle = 0;
}

void xwt::View::GetClassStyle (WNDCLASSEX &wcex) {
	wcex.lpszClassName = _T("_gls_view");
	wcex.cbSize = sizeof(wcex);
	wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hIcon = NULL;
	wcex.hIconSm = NULL;
	wcex.hCursor = ::LoadCursor (NULL, IDC_ARROW);
	wcex.hbrBackground = NULL;
	wcex.lpszMenuName = NULL;
}
#endif

// event handlers...

void xwt::View::OnCreate () {
	Window::OnCreate ();

	// cache window DC for performance
	m_cached_gc = GC::CreateWindowGC (GetHandle());

	// initialize window specific properties
	SetBackgroundColor ( Color(255,255,255) );

	SetDoubleBuffered ( false );
}

void xwt::View::OnPreDestroy () {
	// release cached DC
	if (m_cached_gc) {
		delete m_cached_gc;
		m_cached_gc = NULL;
	}
	xwt::Window::OnPreDestroy ();
}

void xwt::View::OnResize (int cx, int cy) {
	xwt::Window::OnResize (cx, cy);
	CalcLayout ();
}
